const fs = require('fs')
const path = require('path')
const resolve = file => path.resolve(__dirname, file)
const httpProxy = require('http-proxy');
const LRU = require('lru-cache')
const config = require('./config');
const logger = require('./logger');

module.exports = function (app) {

  var insuranceServers = config.INSURANCE_SERVER;
  var apiServers = config.API;

  var proxy = httpProxy.createProxyServer();

  proxy.on('error', function (e) {
    logger.error(e);
  });

  /*
  *接口代理
  */

  app.all('/zaApi/*', function (req, res) {//接口API代理
    var url = req.url;
    console.log('req:', url)
    var regExp = /\/zaApi\/(.*?)\//,
      hostkey = req.url.match(regExp)[1],
      target = '';
    req.url = req.url.replace(regExp, '/');
    target = 'http://' + apiServers[hostkey].host;
    console.log('zaApi:', target + req.url);
    console.log('-------------------------');
    proxy.web(req, res, {
      target: target,
      changeOrigin: true
    });
  });


  /**
   *html输出
   *
   */
  const {createBundleRenderer} = require('vue-server-renderer')
  const isProd = process.env.NODE_ENV === 'production'
  const useMicroCache = process.env.MICRO_CACHE !== 'false'
  const serverInfo =
    `express/${require('express/package.json').version} ` +
    `vue-server-renderer/${require('vue-server-renderer/package.json').version}`

  const template = fs.readFileSync(resolve('../src/views/index.template.html'), 'utf-8')

  function createRenderer(bundle, options) {

    return createBundleRenderer(bundle, Object.assign(options, {
      template,
      // for component caching
      cache: LRU({
        max: 1000,
        maxAge: 1000 * 60 * 15
      }),
      // this is only needed when vue-server-renderer is npm-linked
      basedir: resolve('./assets'),
      // recommended for performance
      runInNewContext: false
    }))
  }

  let renderer
  let readyPromise
  //线上环境
  if (isProd) {
    // In production: create server renderer using built server bundle.
    // The server bundle is generated by vue-ssr-webpack-plugin.
    const bundle = require('../assets/vue-ssr-server-bundle.json')
    // The client manifests are optional, but it allows the renderer
    // to automatically infer preload/prefetch links and directly add <script>
    // tags for any async chunks used during render, avoiding waterfall requests.
    const clientManifest = require('../assets/vue-ssr-client-manifest.json')
    renderer = createRenderer(bundle, {
      clientManifest
    })
  } else {
    //测试环境
    // In development: setup the dev server with watch and hot-reload,
    // and create a new renderer on bundle / index template update.
    readyPromise = require('../build/setup-dev-server')(app, (bundle, options) => {

      renderer = createRenderer(bundle, options)
    })
  }

  // 1-second microcache.
// https://www.nginx.com/blog/benefits-of-microcaching-nginx/
  const microCache = LRU({
    max: 100,
    maxAge: 1000
  })

  // since this app has no user-specific content, every page is micro-cacheable.
  // if your app involves user-specific content, you need to implement custom
  // logic to determine whether a request is cacheable based on its url and
  // headers.
  const isCacheable = req => useMicroCache

  function render(req, res) {
    const s = Date.now()

    res.setHeader("Content-Type", "text/html")
    res.setHeader("Server", serverInfo)

    const handleError = err => {

      if (err.url) {
        res.redirect(err.url)
      } else if (err.code === 404) {
        res.status(404).end('404 | Page Not Found')
      } else {
        // Render Error Page or Redirect
        res.status(500).end('500 | Internal Server Error')
        console.error(`error during render : ${req.url}`)
        console.error(err.stack)
      }
    }

    const cacheable = isCacheable(req)
    if (cacheable) {
      const hit = microCache.get(req.url)
      if (hit) {
        if (!isProd) {
          console.log(`cache hit!`)
        }
        return res.end(hit)
      }
    }

    const context = {
      title: 'vue服务端渲染示例', // default title
      url: req.url,
      cookies: req.cookies
    }
    renderer.renderToString(context, (err, html) => {
      if (err) {
        return handleError(err)
      }
      res.end(html)
      if (cacheable) {
        microCache.set(req.url, html)
      }
      if (!isProd) {
        console.log(`whole request: ${Date.now() - s}ms`)
      }
    })
  }

  app.get('*', isProd ? render : (req, res) => {
    readyPromise.then(() => render(req, res))
  })


};
